#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>

#include "_label.h"
#include "label.h"
#include "_font.h"

#define false       0
#define true        1

#ifdef __DEBUG__
#define __E(fmt, args...) fprintf(stderr, "LABEL ERROR [%d]: " fmt, __LINE__, ## args)
#define __W(fmt, args...) fprintf(stderr, "LABEL WARNING [%d]: " fmt, __LINE__, ## args)
#else
#define __E(fmt, args...)
#define __W(fmt, args...)
#endif

static label labels[LABEL_MAX_NUMBER];
static int lblId = 0;

int label_create(unsigned int x, unsigned int y, unsigned int font_height,
        unsigned char *text, unsigned int font_r, unsigned int font_g, unsigned int font_b) {

    if (lblId > LABEL_MAX_NUMBER) {
        __E("Nao e possivel criar mais labels. Numero maximo.\n");
        return LABEL_FAILURE;
    } else {
        labels[lblId].x = x;
        labels[lblId].y = y + font_height;
        labels[lblId].font_r = font_r;
        labels[lblId].font_g = font_g;
        labels[lblId].font_b = font_b;
        labels[lblId].visible = true;
        labels[lblId].initialized = false;
        labels[lblId].id = lblId;
        labels[lblId].font_height = font_height;
        strcpy(labels[lblId].text, text);
        labels[lblId].winp = NULL;
        labels[lblId].initialized = true;
        return lblId++;
    }
}

signed int label_destroy(signed int labelId) {
    if (!labels[labelId].initialized) {
        __E("Label nao pode ser destruido: label nao foi criado.");
        return LABEL_FAILURE;
    }

    labels[labelId].x = 0;
    labels[labelId].y = 0;
    labels[labelId].font_r = 0;
    labels[labelId].font_g = 0;
    labels[labelId].font_b = 0;
    labels[labelId].font_height = 0;
    labels[labelId].redraw = 0;
    labels[labelId].visible = 0;
    strncpy(labels[labelId].text, "", LABEL_MAX_TEXT);

    label_delFromWindow(labelId);
    labels[labelId].initialized = 0;
    return LABEL_SUCCESS;
}

int label_draw(int labelId) {
    if (labels[labelId].initialized) {
        if (labels[labelId].winp) {
            if (labels[labelId].visible) {
                if (font_render(labels[labelId].text, labels[labelId].x, labels[labelId].y, 0xff, labels[labelId].font_height, labels[labelId].winp, labels[labelId].font_r, labels[labelId].font_g, labels[labelId].font_b) < 0) {
                    return LABEL_FAILURE;
                }

                return LABEL_SUCCESS;
            }
            return LABEL_SUCCESS;
        } else {
            __E("Nenhuma tela associada ao label.\n");
            return LABEL_FAILURE;
        }
    } else {
        __E("Label nao foi criado.\n");
        return LABEL_FAILURE;
    }
}

int label_setText(int labelId, unsigned char *text) {
    if (labels[labelId].initialized) {
        strcpy(labels[labelId].text, text);
        labels[labelId].text[strlen(text)] = '\0';
        return LABEL_SUCCESS;
    } else {
        __E("Label nao foi criado.\n");
        return LABEL_FAILURE;
    }
}

int label_setVisible(int labelId, unsigned char visible) {
    if (labels[labelId].initialized) {
        if (labels[labelId].winp) {
            if (visible == true || visible == false) {
                labels[labelId].visible = visible;
                return LABEL_SUCCESS;
            } else {
                __E("Opcao invalida.\n");
                return LABEL_FAILURE;
            }
        } else {
            __E("Nenhuma tela associada ao label.\n");
            return LABEL_FAILURE;
        }
    } else {
        __E("Label nao foi criado.\n");
        return LABEL_FAILURE;
    }
}

int label_addToWindow(int labelId, int labelId_next, int windowId, window *winp) {
    if (labels[labelId_next].winp == NULL) {
        labels[labelId_next].next = labels[labelId].next;
        labels[labelId].next = &labels[labelId_next];
        labels[labelId_next].previous = &labels[labelId];
        labels[labelId_next].next->previous = &labels[labelId_next];
        labels[labelId_next].winp = winp;
        labels[labelId_next].windowId = windowId;
        return LABEL_SUCCESS;
    } else {
        __E("Ja existe uma tela associada ao label.\n");
        return LABEL_FAILURE;
    }
}

signed int label_delFromWindow(signed int labelId) {
    if (!labels[labelId].initialized) {
        __E("Label nao criado.\n");
        return LABEL_FAILURE;
    }

    if (labels[labelId].winp == NULL) {
        return LABEL_SUCCESS;
    }

    if (labels[labelId].next == &labels[labelId]) {
        labels[labelId].winp->firstLabel = -1;
        labels[labelId].winp->actualLabel = -1;
    } else {
        if (labels[labelId].winp->actualLabel == labelId) {
            labels[labelId].winp->actualLabel = labels[labels[labelId].winp->actualLabel].previous->id;
        } else if (labels[labelId].winp->firstLabel == labelId) {
            labels[labelId].winp->firstLabel = labels[labels[labelId].winp->firstLabel].next->id;
        }

        labels[labelId].previous->next = labels[labelId].next;
        labels[labelId].next->previous = labels[labelId].previous;
    }
    labels[labelId].previous = &labels[labelId];
    labels[labelId].next = &labels[labelId];
    labels[labelId].winp = NULL;
    labels[labelId].windowId = -1;
    window_setComponentsRedraw(labels[labelId].windowId);
    return LABEL_SUCCESS;
}

int label_next(int labelId) {
    if (labels[labelId].initialized) return labels[labelId].next->id;
    else {
        __E("Label nao foi criado.\n");
        return LABEL_FAILURE;
    }
}

int label_previous(int labelId) {
    if (labels[labelId].initialized) return labels[labelId].previous->id;
    else {
        __E("Label nao foi criado.\n");
        return LABEL_FAILURE;
    }
}

int label_setColor(int labelId, unsigned int r, unsigned int g, unsigned int b) {
    if (labels[labelId].initialized) {
        labels[labelId].font_r = r;
        labels[labelId].font_g = g;
        labels[labelId].font_b = b;
        return LABEL_SUCCESS;
    } else {
        __E("Label nao criado.\n");
        return LABEL_FAILURE;
    }
}

signed int label_getX(signed int labelId) {
    if (labels[labelId].initialized) {
        return labels[labelId].x;
    } else {
        __E("Label não foi criado.\n");
        return LABEL_FAILURE;
    }
}

signed int label_getY(signed int labelId) {
    if (labels[labelId].initialized) {
        return labels[labelId].y;
    } else {
        __E("Label não foi criado.\n");
        return LABEL_FAILURE;
    }
}

signed int label_getWidth(signed int labelId) {
    if (labels[labelId].initialized) {
        return font_getStringWidth(labels[labelId].text, labels[labelId].font_height);
    } else {
        __E("Label não foi criado.\n");
        return LABEL_FAILURE;
    }
}

signed int label_getHeight(signed int labelId) {
    if (labels[labelId].initialized) {
        return font_getStringHeight(labels[labelId].text, labels[labelId].font_height);
    } else {
        __E("Label não foi criado.\n");
        return LABEL_FAILURE;
    }
}

void label_setRedraw(signed int labelId) {
    labels[labelId].redraw = 1;
}
